package co.forsaken.projectindigo.managers; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Random; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; import javax.crypto.CipherOutputStream; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import co.forsaken.projectindigo.data.UserPassword; import co.forsaken.projectindigo.data.log.Logger; import co.forsaken.projectindigo.gui.MainPanel; import co.forsaken.projectindigo.gui.ProgressPanel; import co.forsaken.projectindigo.utils.DirectoryLocations; public class UserManager { protected Map<String, UserPassword> usernames = new LinkedHashMap<String, UserPassword>(); public UserManager(MainPanel mainPanel) { readSavedUsernames(mainPanel); ((ProgressPanel) mainPanel.getPanel(-1)).stateChanged("Finished Loading Users", "", 100); mainPanel.switchPage(0); } public final List<String> getSavedAccounts() { return new ArrayList<String>(usernames.keySet()); } public final boolean hasSavedPassword(String user) { return (usernames.containsKey(user)) && (usernames.get(user) != null); } public final String getSavedPassword(String user) { UserPassword pass = usernames.get(user); if (!pass.isHash()) { return pass.getPassword(); } return null; } public final String getUsername(String account) { for (String key : usernames.keySet()) { if (key.equalsIgnoreCase(account)) { UserPassword pass = usernames.get(key); return pass.getUsername(); } } return account; } public final boolean removeAccount(String account) { Iterator<Entry<String, UserPassword>> i = usernames.entrySet().iterator(); while (i.hasNext()) { Map.Entry<String, UserPassword> e = i.next(); if (((String) e.getKey()).equalsIgnoreCase(account)) { i.remove(); return true; } } return false; } public final String getAccountKey(String username) { for (String s : usernames.keySet()) { if (usernames.get(s).getUsername().equalsIgnoreCase(username)) { return s; } } return ""; } public final String getAccountName(String username) { if (usernames.containsKey(username)) { return usernames.get(username).getUsername(); } return username; } public final void clear() { usernames.clear(); } public final void saveUsername(String key, String user, String pass) { if ((!hasSavedPassword(key)) && (pass != null) && (!pass.isEmpty())) { usernames.put(key, new UserPassword(pass, user)); } } private void readSavedUsernames(MainPanel mainPanel) { try { File lastLogin = new File(DirectoryLocations.BACKEND_DATA_DIR.format("lastlogin.dat")); if (!lastLogin.exists()) { return; } ((ProgressPanel) mainPanel.getPanel(-1)).stateChanged("Loading stored users...", "", 80); Cipher cipher = getCipher(2, "passwordfile"); DataInputStream dis; if (cipher != null) dis = new DataInputStream(new CipherInputStream(new FileInputStream(lastLogin), cipher)); else { dis = new DataInputStream(new FileInputStream(lastLogin)); } try { int extra = 5; while (true) { String key = dis.readUTF(); String user = dis.readUTF(); ((ProgressPanel) mainPanel.getPanel(-1)).stateChanged("Loading " + user + "...", "", 80 + extra); extra += 5; boolean isHash = dis.readBoolean(); if (isHash) { byte[] hash = new byte[32]; dis.read(hash); usernames.put(key, new UserPassword(hash, user)); } else { String pass = dis.readUTF(); usernames.put(key, new UserPassword(pass, user)); } } } catch (EOFException e) { dis.close(); } } catch (Exception e) {} } public final void writeUsernameList() { DataOutputStream dos = null; try { File lastLogin = new File(DirectoryLocations.BACKEND_DATA_DIR.format("lastlogin.dat")); Cipher cipher = getCipher(1, "passwordfile"); if (cipher != null) { dos = new DataOutputStream(new CipherOutputStream(new FileOutputStream(lastLogin), cipher)); } else { dos = new DataOutputStream(new FileOutputStream(lastLogin, true)); } for (String user : usernames.keySet()) { UserPassword pass = (UserPassword) usernames.get(user); if (pass.getUsername() == null) { pass.setUsername(user); } dos.writeUTF(user); dos.writeUTF(pass.getUsername()); dos.writeBoolean(pass.isHash()); if (pass.isHash()) { dos.write(pass.getPasswordHash()); } else { dos.writeUTF(pass.getPassword()); } } } catch (Exception e) { Logger.logError(e.getMessage(), e); } finally { if (dos != null) { try { dos.close(); } catch (IOException e) {} } } } private static final Cipher getCipher(int mode, String password) throws Exception { Random random = new Random(43287234L); byte[] salt = new byte[8]; random.nextBytes(salt); PBEParameterSpec pbeParamSpec = new PBEParameterSpec(salt, 5); SecretKey pbeKey = SecretKeyFactory.getInstance("PBEWithMD5AndDES").generateSecret(new PBEKeySpec(password.toCharArray())); Cipher cipher = Cipher.getInstance("PBEWithMD5AndDES"); cipher.init(mode, pbeKey, pbeParamSpec); return cipher; } }